home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '87 / DA's / Crabs+.c < prev    next >
C/C++ Source or Header  |  1987-01-18  |  7KB  |  232 lines

  1. /* This is Crabs+, a rewriting of the famous Crabs DA into LightSpeedC.
  2.     It has been written with LsC2.01 by Daniel Ranson from the original
  3.     code in MacC. Contrary to the latter, this code will work on all
  4.     macs, and in all application that supports DAs.
  5.     To compile this, build a DA project with this file and MacTraps.
  6.     It should work with all versions of LsC.
  7.     My contribution, apart from the conversion to LsC, consists of
  8.     two tricks:
  9.     - The screen bitmap is found from the Window Manager port. This
  10.     is more reliable than using QuickDraw because: 1/ QuickDraw
  11.     globals are not DA globals. 2/ The application can choose where
  12.     it places QuickDraw globals. There are at least two favored
  13.     positions: -4(a5) and 0(a5). This is unreliable.
  14.     - When we CopyBits to the screen, the port is changed to a fake
  15.     port to prevent clipping. Without that, in the Finder with nothing
  16.     selected and the mouse outside any window, the crabs will only
  17.     draw OUTSIDE the windows.
  18.     
  19.     There was no copyright notice in the original program I found, so
  20.     I don't add any. Feel free to dump this in your favorite trashcan
  21.     (real or iconic).
  22.             Daniel Ranson.
  23.  */
  24.  
  25. /* Includes */
  26. #include    <QuickDraw.h>
  27. #include    <DeviceMgr.h>
  28.  
  29. /* Global variables */
  30. short    already_open = 0;        /*  1 -> DA is already open  */
  31. DCtlPtr    dce;                /*  device control entry  */
  32. BitMap    grayMap, crabMap;
  33. BitMap    *screenPtr;            /* Pointer to screen bitmap */
  34. GrafPort    fakePort;
  35. Rect    crabRect, topleftRect, drawRect;
  36. Ptr        grayPtr, crabPtr;
  37. unsigned    long    grayBits[] = {
  38.                         0xAAAA5555,
  39.                         0xAAAA5555,
  40.                         0xAAAA5555,
  41.                         0xAAAA5555,
  42.                         0xAAAA5555,
  43.                         0xAAAA5555,
  44.                         0xAAAA5555,
  45.                         0xAAAA5555};
  46. unsigned    long    crabBits[] = {
  47.                         0xBEAA7755,
  48.                         0xAAAA7F55,
  49.                         0xBEAA7F55,
  50.                         0xAAAA5555,
  51.                         0xAAAA5555,
  52.                         0xAAAA5555,
  53.                         0xAAAA5555,
  54.                         0xAAAA5555}; 
  55. short    crabCount, maxCrabs;
  56. Point    crabWhere[40];
  57.  
  58. #define    MBarHeight    *(short*)0xBAA
  59.  
  60. main(p, d, n)
  61. cntrlParam    *p;            /*  ==> parameter block  */
  62. DCtlPtr        d;            /*  ==> device control entry  */
  63. short        n;            /*  entry point selector  */
  64. {
  65.         /*  check to make sure our data area was allocated  */
  66.         
  67.     if (d->dCtlStorage == 0) {
  68.         if (n == 0) {    /*  open  */
  69.             SysBeep(3);
  70.             CloseDriver(d->dCtlRefNum);
  71.         }
  72.         return(0);
  73.     }
  74.     
  75.     /*  dispatch  */
  76.     dce = d;
  77.     switch(n){
  78.     case 0:        /*  open  */
  79.         doOpen();
  80.         break;
  81.     
  82.     case 2:        /*  control  */
  83.         if(p->csCode == accRun){    /*  The real thing  */
  84.             doRun();
  85.         }
  86.         break;
  87.     
  88.     default:    /* Ignore all prayers */
  89.         break;
  90.     }
  91.     
  92.     /*  done  */
  93.     return(0);    /* No Error */
  94. }
  95.  
  96. /* Open routine */
  97. doOpen()
  98. {
  99.      register    short    whichCrab, i;
  100.      GrafPtr        wPort, savedPort;
  101.  
  102.      /*  every time ...  */
  103.     dce->dCtlFlags |= dNeedLock|dNeedTime;
  104.     dce->dCtlDelay = 10;    /* Call every 10 ticks */
  105.     dce->dCtlEMask = 0;        /* No events processed !! */
  106.     if(already_open)
  107.         return;
  108.     
  109.     /*  first time only ...  */
  110.     already_open = 1;
  111.     /* Find screen bitmap through Window Manager port */
  112.     GetWMgrPort(&wPort);
  113.     screenPtr = &(wPort->portBits);
  114.     
  115.     /*set up bitmaps for the screen, the crab, and the gray stuff the crabs
  116.         leave behind.  The latter 2 bitmaps are bigger than they really
  117.         need to be because of the constraint that rowBytes must be even*/
  118.     
  119.     grayPtr = NewPtr(32L);
  120.     crabPtr = NewPtr(32L);
  121.     SetRect(&crabRect,0,0,16,16);
  122.     SetRect(&topleftRect,0,0,8,8);
  123.     BlockMove(grayBits, grayPtr, 32L);
  124.     grayMap.baseAddr = grayPtr;
  125.     grayMap.rowBytes = 2;
  126.     grayMap.bounds = crabRect;
  127.     BlockMove(crabBits, crabPtr, 32L);
  128.     crabMap.baseAddr = crabPtr;
  129.     crabMap.rowBytes = 2;
  130.     crabMap.bounds = crabRect;
  131.     
  132.     /*allocate a random # of crabs to starting positions down the left 
  133.       edge of the screen, starting just below the menu bar */
  134.     
  135.     maxCrabs = (screenPtr->bounds.bottom - screenPtr->bounds.top
  136.                     - MBarHeight) / 8;
  137.     if(maxCrabs > 40) maxCrabs = 40;
  138.     for(i = 0, whichCrab = 0; i < maxCrabs; i++)
  139.         if(Random() & 0x0001){
  140.             crabWhere[whichCrab].h = screenPtr->bounds.left;
  141.             crabWhere[whichCrab].v = MBarHeight + i * 8;
  142.             whichCrab++;
  143.         }
  144.     crabCount = whichCrab;    /* keep track of how many crabs were allocated */
  145.     
  146.     /* Create a fake port to prevent CopyBits clipping */
  147.     GetPort(&savedPort);
  148.     OpenPort(&fakePort);
  149.     /* paste the top left corner of the crab bitmap ( i.e., the crab itself)
  150.         in each crab's starting position on the screen */
  151.     
  152.     for(whichCrab = 0; whichCrab < crabCount; whichCrab++){
  153.         SetRect(&drawRect,
  154.                 crabWhere[whichCrab].h,
  155.                 crabWhere[whichCrab].v,
  156.                 crabWhere[whichCrab].h + 8,
  157.                 crabWhere[whichCrab].v + 8);
  158.         CopyBits(&crabMap, screenPtr,
  159.                     &topleftRect, &drawRect, srcCopy, 0L);
  160.     }
  161.     SetPort(savedPort);
  162. }
  163.  
  164. /* Run routine */
  165. doRun(){
  166.     short offset,voffset,sign;
  167.      register    short    whichCrab;
  168.      GrafPtr        savedPort;
  169.     
  170.     GetPort(&savedPort);
  171.     SetPort(&fakePort);
  172.     /*first, replace all the current crabs with gray*/
  173.     for(whichCrab = 0; whichCrab < crabCount; whichCrab++){
  174.         SetRect(&drawRect,
  175.                 crabWhere[whichCrab].h,
  176.                 crabWhere[whichCrab].v,
  177.                 crabWhere[whichCrab].h + 8,
  178.                 crabWhere[whichCrab].v + 8);
  179.         CopyBits(&grayMap, screenPtr,
  180.                     &topleftRect, &drawRect, srcCopy, 0L);
  181.     }
  182.     
  183.     /* change each crab's position a little bit vertically,
  184.         somewhat more horizontally */
  185.     for(whichCrab = 0; whichCrab < crabCount; whichCrab++){
  186.         offset = (Random() & 0x0003);        /* offset = 0,1,2, or 3*/
  187.         sign = ((Random() & 0x0001)? 1 : -1);    /* + or - */
  188.         /* +/- 2,4,6, or 8 horiz */
  189.         crabWhere[whichCrab].h = 
  190.                 (crabWhere[whichCrab].h + sign * (2+2*offset));
  191.         /* Wraparound */
  192.         if(crabWhere[whichCrab].h + 8 >= screenPtr->bounds.right)
  193.             crabWhere[whichCrab].h = screenPtr->bounds.left;
  194.         else if(crabWhere[whichCrab].h < screenPtr->bounds.left)
  195.             crabWhere[whichCrab].h = screenPtr->bounds.right - 8;
  196.         voffset = (Random() & 0x0003);
  197.         switch(voffset){
  198.         case 0:
  199.             crabWhere[whichCrab].v = (crabWhere[whichCrab].v - 2);
  200.             /* Wraparound */
  201.             if(crabWhere[whichCrab].v + 8 >= screenPtr->bounds.bottom)
  202.                 crabWhere[whichCrab].v = screenPtr->bounds.top;
  203.             else if(crabWhere[whichCrab].v < screenPtr->bounds.top)
  204.                 crabWhere[whichCrab].v = screenPtr->bounds.bottom - 8;
  205.             break;
  206.         
  207.         case 1:
  208.         case 2:
  209.             break;
  210.         
  211.         case 3:
  212.             crabWhere[whichCrab].v = (crabWhere[whichCrab].v + 2)
  213.                     % (screenPtr->bounds.bottom - screenPtr->bounds.top);
  214.             break;
  215.         
  216.         default:
  217.             break;
  218.         }
  219.     }
  220.                 
  221.     /* redraw the little buggers */
  222.     for(whichCrab=0;whichCrab<crabCount;whichCrab++){
  223.         SetRect(&drawRect,
  224.                 crabWhere[whichCrab].h,
  225.                 crabWhere[whichCrab].v,
  226.                 crabWhere[whichCrab].h + 8,
  227.                 crabWhere[whichCrab].v + 8);
  228.         CopyBits(&crabMap, screenPtr, &topleftRect, &drawRect, srcCopy, 0L);
  229.     }
  230.     SetPort(savedPort);
  231. }
  232.